﻿namespace TfsCloudDeploy.Workflow.Core.Activities
{
    using System.Activities;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using Microsoft.TeamFoundation.Build.Client;
    using Microsoft.TeamFoundation.Build.Workflow.Activities;
    using Microsoft.TeamFoundation.Build.Workflow.Design;
    using Microsoft.TeamFoundation.Build.Workflow.Tracking;
    using Microsoft.TeamFoundation.VersionControl.Client;

    [Designer(typeof(TeamBuildBaseActivityDesigner)), SRDescription(typeof(ExtendedWorkflowResources), "SetWorkspaceMappingsDescription"), BuildActivity(HostEnvironmentOption.All), BuildCategory, ToolboxBitmap(typeof(TeamBuildBaseActivityDesigner), "DefaultBuildIcon.png"), ActivityTracking(ActivityTrackingOption.ActivityOnly)]
    public class SetWorkspaceMappings : CodeActivity
    {
        [SRDescription(typeof(ExtendedWorkflowResources), "CustomWorkspaceMappingsDescription"), SRCategory(typeof(ExtendedWorkflowResources), "ActivityCategoryMiscellaneous"), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), RequiredArgument]
        public InArgument<VersionedServerMapping[]> CustomWorkspaceMappings { get; set; }

        [SRDescription(typeof(ExtendedWorkflowResources), "SourcesDirectoryDescription"), SRCategory(typeof(ExtendedWorkflowResources), "ActivityCategoryMiscellaneous"), DesignerSerializationVisibility(DesignerSerializationVisibility.Visible), RequiredArgument]
        public InArgument<string> SourcesDirectory { get; set; }

        protected override void Execute(CodeActivityContext context)
        {
            WorkflowUtility.CreateBuildMessage("SetWorkspaceMappings: Setting custom mappings...", context);

            VersionedServerMapping[] customWorkspaceMappings = this.CustomWorkspaceMappings.Get(context);

            if (customWorkspaceMappings.Length == 0)
            {
                return;
            }

            this.WriteCustomMappingsToLog(customWorkspaceMappings, context);

            IBuildDetail buildDetail = context.GetExtension<IBuildDetail>();

            // Normalize/convert the working folder mappings to server mappings (replace $(SourceDir), *, etc...):
            IDictionary<string, string> additionalVariableReplacements = new Dictionary<string, string>();
            string sourcesDirectory = this.SourcesDirectory.Get(context);
            additionalVariableReplacements.Add(VersionControlHelper.SourceDirEnvironmentVariable, sourcesDirectory);
            
            ServerMapping<string>[] serverMappings = VersionControlHelper.GetWorkspaceMappingsFromVersionedServerMappings(customWorkspaceMappings, additionalVariableReplacements);
            this.WriteNormalizedMappingsToLog(serverMappings, context);

            buildDetail.BuildDefinition.Workspace.Mappings.Clear();
            foreach (var mapping in serverMappings)
            {
                buildDetail.BuildDefinition.Workspace.AddMapping(mapping.ServerItem, mapping.MappedItem, (mapping.MappingType == WorkingFolderType.Map) ? WorkspaceMappingType.Map : WorkspaceMappingType.Cloak, (mapping.Depth == RecursionType.OneLevel) ? WorkspaceMappingDepth.OneLevel : WorkspaceMappingDepth.Full);
            }
        }

        private void WriteCustomMappingsToLog(VersionedServerMapping[] customWorkspaceMappings, CodeActivityContext context)
        {
            WorkflowUtility.CreateBuildMessage(string.Format("{0} Custom Mappings:", customWorkspaceMappings.Length), context);
            foreach (var customWorkspaceMapping in customWorkspaceMappings)
            {
                WorkflowUtility.CreateBuildMessage(
                    string.Format("Local Item: {0}, Server Item: {1}, Mapping Type: {2}, Baseline Version: {3}.",
                        customWorkspaceMapping.LocalItem, customWorkspaceMapping.ServerItem, customWorkspaceMapping.MappingType, customWorkspaceMapping.BaselineVersion),
                    context);
            }
        }

        private void WriteNormalizedMappingsToLog(ServerMapping<string>[] serverMappings, CodeActivityContext context)
        {
            WorkflowUtility.CreateBuildMessage(string.Format("{0} Normalized Mappings:", serverMappings.Length), context);
            foreach (var serverMapping in serverMappings)
            {
                WorkflowUtility.CreateBuildMessage(
                    string.Format("Local Item: {0}, Server Item: {1}, Depth: {2}, Display Server Item: {3}, Is Cloaked: {4}, Baseline Version: {5}.",
                        serverMapping.MappedItem, serverMapping.ServerItem, serverMapping.Depth, serverMapping.DisplayServerItem, serverMapping.IsCloaked, serverMapping.BaselineVersion),
                    context);
            }
        }
    }
}
